package com.huawei.lynnbit.tool.cocos.processor.preset;

import com.google.common.collect.Lists;
import com.huawei.lynnbit.tool.cocos.config.game.GameConfig;
import com.huawei.lynnbit.tool.cocos.config.game.PackageType;
import com.huawei.lynnbit.tool.cocos.config.game.task.*;
import com.huawei.lynnbit.tool.cocos.processor.CompositeProcessor;
import com.huawei.lynnbit.tool.cocos.processor.Processor;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;

@Slf4j
public class PackageProcessor implements Processor {
    public static final String TOOLS_NODE_NODE_EXE = "\\tools\\node\\node.exe";
    public static final String TOOLS_HVIGOR_BIN_HVIGORW_JS = "\\tools\\hvigor\\bin\\hvigorw.js";
    private GameConfig gameConfig;

    public PackageProcessor(GameConfig config) {
        this.gameConfig = config;
    }

    private String getOutputFile(String needOutput, PackageType type) {
        File needOutputDir = new File(needOutput);
        File[] files = needOutputDir.listFiles();
        for (File file : files) {
            if (!file.isFile()) {
                continue;
            }

            if (!file.getName().endsWith(type.name().toLowerCase(Locale.ROOT))) {
                continue;
            }


            if (file.getName().contains("unsigned")) {
                continue;
            }

            return file.getAbsolutePath();
        }

        throw new IllegalStateException("no output in " + needOutput);
    }

    @Override
    public void process() throws Exception {
        log.info("start to package >>>>>>>>>>>>>>>>>>>>>>>>");
        List<Task> taskList = new ArrayList<>();

        taskList.addAll(getOhpmInstallProcessTask());
        taskList.addAll(getSignProcessTask());
        taskList.addAll(getPackageProcessTask());
        Processor compositeProcessor = new CompositeProcessor(taskList, gameConfig);
        compositeProcessor.process();

        taskList.clear();
        taskList.addAll(getCopyOutputProcessTask());
        taskList.addAll(installHapProcessTask());
        compositeProcessor = new CompositeProcessor(taskList, gameConfig);
        compositeProcessor.process();
    }

    private Collection<? extends Task> getOhpmInstallProcessTask() {
        CmdTask rootInstall = CmdTask.builder()
                .stage(Stage.PACKAGE)
                .type(Task.TYPE_CMD)
                .runDir(gameConfig.getDevEcoProjectPath())
                .runCmd("cmd /c ohpm install")
                .build();
        CmdTask entryInstall = CmdTask.builder()
                .stage(Stage.PACKAGE)
                .type(Task.TYPE_CMD)
                .runDir(gameConfig.getDevEcoProjectPath() + "\\entry")
                .runCmd("cmd /c ohpm install")
                .build();

        return Lists.newArrayList(rootInstall, entryInstall);
    }

    private Collection<? extends Task> getSignProcessTask() {
        ReplaceStringTask replaceSigningConfig = ReplaceStringTask.builder()
                .stage(Stage.PACKAGE)
                .type(Task.TYPE_REPLACE_STRING)
                .srcPath(gameConfig.getDevEcoProjectPath() + "\\build-profile.json5")
                .srcPattern("\"signingConfigs\"\s*:\s*\\[.*(\n|\r\n).*(\n|\r\n).*(\n|\r\n).*(\n|\r\n).*(\n|\r\n).*(\n|\r\n).*(\n|\r\n).*(\n|\r\n).*(\n|\r\n).*(\n|\r\n).*(\n|\r\n).*(\n|\r\n).*(\n|\r\n).*(\n|\r\n)\s*\\]")
                .destString("\"signingConfigs\": [\n" +
                        "      {\n" +
                        "        \"name\": \"default\",\n" +
                        "        \"type\": \"HarmonyOS\",\n" +
                        "        \"material\": {\n" +
                        "          \"certpath\": \"" + gameConfig.getPackageInfo().getCertPath().replaceAll("\\\\", "\\\\\\\\") + "\",\n" +
                        "          \"keyAlias\": \"" + gameConfig.getPackageInfo().getKeyAlias() + "\",\n" +
                        "          \"keyPassword\": \"" + gameConfig.getPackageInfo().getKeyPassword() + "\",\n" +
                        "          \"profile\": \"" + gameConfig.getPackageInfo().getProfile().replaceAll("\\\\", "\\\\\\\\") + "\",\n" +
                        "          \"signAlg\": \"SHA256withECDSA\",\n" +
                        "          \"storeFile\": \"" + gameConfig.getPackageInfo().getStoreFile().replaceAll("\\\\", "\\\\\\\\") + "\",\n" +
                        "          \"storePassword\": \"" + gameConfig.getPackageInfo().getStorePassword() + "\"\n" +
                        "        }\n" +
                        "      }\n" +
                        "    ]").build();

        return Lists.newArrayList(replaceSigningConfig);
    }

    private Collection<? extends Task> getPackageProcessTask() {
        CmdTask packageHap = CmdTask.builder()
                .stage(Stage.PACKAGE)
                .type(Task.TYPE_CMD)
                .runDir(gameConfig.getDevEcoProjectPath())
                .runCmd("\"" + gameConfig.getSystemConfig().getDevEcoInstallPath() + TOOLS_NODE_NODE_EXE + "\" \"" + gameConfig.getSystemConfig().getDevEcoInstallPath() + TOOLS_HVIGOR_BIN_HVIGORW_JS + "\" --mode module -p module=entry@default -p product=default -p requiredDeviceType=phone assembleHap --analyze=normal --parallel --incremental --daemon").build();

        CmdTask packageApp = CmdTask.builder()
                .stage(Stage.PACKAGE)
                .type(Task.TYPE_CMD)
                .runDir(gameConfig.getDevEcoProjectPath())
                .runCmd("\"" + gameConfig.getSystemConfig().getDevEcoInstallPath() + TOOLS_NODE_NODE_EXE + "\" \"" + gameConfig.getSystemConfig().getDevEcoInstallPath() + TOOLS_HVIGOR_BIN_HVIGORW_JS + "\" --mode module -p module=entry@default -p product=default -p requiredDeviceType=phone assembleApp --analyze=normal --parallel --incremental --daemon").build();

        if (PackageType.HAP.equals(gameConfig.getPackageInfo().getType())) {
            return Lists.newArrayList(packageHap);
        } else {
            return Lists.newArrayList(packageApp);
        }
    }

    private List<Task> getCopyOutputProcessTask() {
        String fileName = gameConfig.getAppInfo().getAppName() + "_" + gameConfig.getAppInfo().getAppId();
        CopyFileTask copyOutPutTask = CopyFileTask.builder()
                .stage(Stage.PACKAGE)
                .type(Task.TYPE_COPY_FILE)
                .srcPath(getOutputFile(gameConfig.getOutputPath(), gameConfig.getPackageInfo().getType()))
                .destPath(gameConfig.getSystemConfig().getOutput() + "\\" + fileName + "\\" + fileName + "." + gameConfig.getPackageInfo().getType().toName().toLowerCase(Locale.ROOT))
                .build();
        return Lists.newArrayList(copyOutPutTask);
    }

    private List<Task> installHapProcessTask() {
        String fileName = gameConfig.getAppInfo().getAppName() + "_" + gameConfig.getAppInfo().getAppId();
        CmdTask installHap = CmdTask.builder()
                .stage(Stage.PACKAGE)
                .type(Task.TYPE_CMD)
                .runDir(gameConfig.getSystemConfig().getOutput() + "\\" + fileName)
                .runCmd("hdc install " + fileName + "." + gameConfig.getPackageInfo().getType().toName().toLowerCase(Locale.ROOT))
                .build();

        if (PackageType.HAP.equals(gameConfig.getPackageInfo().getType())) {
            return Lists.newArrayList(installHap);
        } else {
            return new ArrayList<>();
        }
    }
}
